﻿Option Strict On
Option Explicit On
Option Infer On

Imports System
Imports System.Linq
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module GeneralExtensions
   <Extension()> _
   Public Function SubstringAfterLast _
             (ByVal initialString As String, _
              ByVal findString As String) _
              As String
      Dim iPos = initialString.LastIndexOf(findString)
      Return initialString.Substring(iPos + 1)
   End Function

   <Extension()> _
   Public Function ContainsBits(ByVal checkIn As Int32, ByVal checkFor As Int32) As Boolean
      Return (checkIn And checkFor) = checkFor
   End Function

   <Extension()> _
   Public Function ContainsBits(ByVal checkIn As Int64, ByVal checkFor As Int64) As Boolean
      Return (checkIn And checkFor) = checkFor
   End Function

   <Extension()> _
   Public Function Increment(ByRef i As Int32) As Int32
      i = i + 1
      Return i
   End Function

   <Extension()> _
   Public Function IsNullOrEmpty(Of T)(ByVal list As IEnumerable(Of T)) As Boolean
      If list Is Nothing OrElse list.Count = 0 Then
         Return True
      End If
      Return False
   End Function

   <Extension()> _
   Public Function ContainsString(ByVal searchIn As String, ByVal searchFor As String) As Boolean
      If searchIn Is Nothing Then
         Return False
      End If
      Return searchIn.Contains(searchFor)
   End Function

   <Extension()> _
   Public Function EqualsIgnoreCase( _
            ByVal string1 As String, _
            ByVal string2 As String) _
            As Boolean
      If string1 Is Nothing OrElse string2 Is Nothing Then
         Return False
      End If
      Return string1.Equals(string2, StringComparison.InvariantCultureIgnoreCase)
   End Function

   <Extension()> _
   Public Function ContainsIgnoreCase( _
            ByVal string1 As String, _
            ByVal string2 As String) _
            As Boolean
      ' LOCALIZATION: THis is a hack to test in other languages
      Return string1.ToUpper.Contains(string2.ToUpper)
   End Function

   <Extension()> _
   Public Function EndsWithIgnoreCase( _
            ByVal string1 As String, _
            ByVal string2 As String) _
            As Boolean
      Return string1.EndsWith(string2, StringComparison.InvariantCultureIgnoreCase)
   End Function

   <Extension()> _
   Public Function SubstringBefore( _
            ByVal searchIn As String, _
            ByVal searchFor As String) _
            As String
      Dim pos = searchIn.IndexOf(searchFor)
      Return searchIn.Substring(0, pos)
   End Function

   <Extension()> _
   Public Function SubstringAfter( _
            ByVal searchIn As String, _
            ByVal searchFor As String) _
            As String
      Dim pos = searchIn.IndexOf(searchFor)
      Return searchIn.Substring(pos + searchFor.Length)
   End Function

   <Extension()> _
   Public Function NumberNameSpecifier(ByVal i As Int32) As String
      ' TODO: Rename this function when you figure out what these are called
      Select Case i
         Case 1
            Return "Single"
         Case 2
            Return "Two"
         Case 3
            Return "Three"
         Case 4
            Return "Four"
         Case 5
            Return "Five"
         Case 6
            Return "Six"
         Case 7
            Return "Seven"
         Case 8
            Return "Eight"
         Case 9
            Return "Nine"
         Case 10
            Return "Ten"
         Case Else
            Throw New ArgumentException("This value not supported")
      End Select
   End Function

   <Runtime.CompilerServices.Extension()> _
   Public Function SpaceAtCaps(ByVal s As String) As String
      ' The name is legacy, this also replaces underscores
      Dim chars() As Char = s.ToCharArray
      Dim sb As New Text.StringBuilder

      For i As Int32 = 0 To chars.GetUpperBound(0)
         If chars(i) = "_" Then
            sb.Append(" ")
         Else
            If (i > 0) AndAlso (IsSpaceChar(chars(i)) And Not IsSpaceChar(chars(i - 1))) Then
               sb.Append(" ")
            End If
            sb.Append(chars(i))
         End If
      Next
      Return sb.ToString
   End Function
   Private Function IsSpaceChar(ByVal c As Char) As Boolean
      Return System.Char.IsUpper(c) Or System.Char.IsNumber(c)
   End Function

   <Extension()> _
   Public Function Add(ByVal guid1 As Guid, ByVal guid2 As Guid) As Guid
      Dim s1 = guid1.ToString()
      Dim s2 = guid2.ToString()
      Dim sb As New Text.StringBuilder
      For i = 0 To s1.Length - 1
         If s1(i) = "-"c Then
            sb.Append(s1(i))
         Else
            Dim i1 = Convert.ToInt32(s1(i), 16)
            Dim i2 = Convert.ToInt32(s2(i), 16)
            sb.Append(((i1 + i2) Mod 16).ToString("X"))
         End If
      Next
      Return New Guid(sb.ToString)
   End Function

End Module

Public Module [String]
   Public Function Spaces(ByVal count As Int32) As String
      Return New String(" "c, count)
   End Function

   <System.Runtime.CompilerServices.Extension()> _
   Public Function IsTrue(ByVal value As String) As Boolean
      If String.IsNullOrEmpty(value) Then
         Return False
      Else
         Return value.EqualsIgnoreCase("true")
      End If
   End Function

   <System.Runtime.CompilerServices.Extension()> _
   Public Function FormatString(ByVal format As String, ByVal ParamArray args() As Object) As String
      If String.IsNullOrEmpty(format) Then
         Return String.Empty
      End If
      Return String.Format(format, args)
   End Function

   <System.Runtime.CompilerServices.Extension()> _
   Public Function camelCase(ByVal name As String) As String
      Dim chr = name.Chars(0)
      If Char.IsUpper(name.Chars(0)) Then
         Char.ToLowerInvariant(name.Chars(0))
      End If
      Return name
   End Function

End Module
